<?php

class HttpHelper
{
    /**
     * http GET请求
     * @param  string url address
     * @param  integer timeout data,ms
     * @param  array http header data
     * @return array request result
     */
    public static function curl($url, $timeout = 1000, $header = [])
    {
        $new_ch = curl_init();
        curl_setopt($new_ch, CURLOPT_URL, $url);
        curl_setopt($new_ch, CURLOPT_TIMEOUT_MS, $timeout);
        curl_setopt($new_ch, CURLOPT_RETURNTRANSFER, true);
        if(!empty($header) && is_array($header)){
            curl_setopt($new_ch, CURLOPT_HTTPHEADER, $header);
        }

        $result = curl_exec($new_ch);
        $http_status = curl_getinfo($new_ch, CURLINFO_HTTP_CODE);

        if(curl_errno($new_ch)){
            return false;
        }
        curl_close($new_ch);
        if($http_status != 200){
            return false;
        }
        return $result;
    }

    /**
     * http GET请求
     * @param  string url address
     * @param  array post data
     * @param  integer timeout data, ms
     * @param  array header data
     * @return array request result
     */
    public static function curlPost($url, $curlPost, $timeout = 45000, $header = '')
    {
        $new_ch = curl_init();
        curl_setopt($new_ch, CURLOPT_URL, $url);
        curl_setopt($new_ch, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_0);
        curl_setopt($new_ch, CURLOPT_USERAGENT, "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.)");
        curl_setopt($new_ch, CURLOPT_TIMEOUT_MS, $timeout);
        if(!empty($header) && is_array($header)){
            curl_setopt($new_ch, CURLOPT_HTTPHEADER, $header);
        }
        curl_setopt($new_ch, CURLOPT_RETURNTRANSFER, true);
        curl_setopt($new_ch, CURLOPT_POST, true);
        curl_setopt($new_ch, CURLOPT_POSTFIELDS, $curlPost);
        $result = curl_exec($new_ch);
        $http_status = curl_getinfo($new_ch, CURLINFO_HTTP_CODE);
        if(curl_errno($new_ch)){
            return false;
        }
        curl_close($new_ch);
        if($http_status != 200){
            return false;
        }
        return $result;
    }

    /**
     * 文件传输
     * @param $url
     * @param $file
     * @param int $timeout
     * @param array $header
     * @return bool|mixed
     */
    public static function curlPostFile($url, $fields, $timeout = 45000, $header = [])
    {
        $ch = curl_init();
        curl_setopt($ch, CURLOPT_URL, $url);
        curl_setopt($ch, CURLOPT_POST, true);
        curl_setopt($ch, CURLOPT_POSTFIELDS, $fields);
        curl_setopt($ch, CURLOPT_TIMEOUT_MS, $timeout);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
        curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
        if($header){
            array_push($header, 'Expect:');
        }else{
            $header = ['Expect:'];
        }
        curl_setopt($ch, CURLOPT_HTTPHEADER, $header);
        $content = curl_exec($ch);
        $http_code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
        return $http_code == 200 ? $content : false;
    }

    /**
     * curl cookie
     * @param $url
     * @param $cookie
     * @param int $timeout
     * @return bool|mixed
     */
    public static function curlCookie($url, $cookie, $timeout = 45000)
    {
        $curlCookie = '';
        foreach($cookie as $key => $value){
            $curlCookie .= $key.'='.$value.';';
        }
        $curlCookie = rtrim($curlCookie, ';');

        $ch = curl_init();

        curl_setopt($ch, CURLOPT_URL, $url);
        curl_setopt($ch, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_0);
        curl_setopt($ch, CURLOPT_USERAGENT, "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.)");
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
        curl_setopt($ch, CURLOPT_TIMEOUT_MS, $timeout);
        curl_setopt($ch, CURLOPT_COOKIE, $curlCookie);
        curl_setopt($ch, CURLOPT_REFERER, 'http://mp.btime.com');

        $result = curl_exec($ch);
        $http_code = curl_getinfo($ch, CURLINFO_HTTP_CODE);

        curl_close($ch);

        if($http_code != 200){
            return false;
        }

        return $result;
    }

    /**
     * @param $url
     * @param bool $body
     * @param int $timeout
     * @return array|bool
     */
    public static function curlHeader($url, $body = true, $timeout = 45000)
    {
        $ch = curl_init();
        curl_setopt($ch, CURLOPT_URL, $url);
        curl_setopt($ch, CURLOPT_HEADER, true);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
        curl_setopt($ch, CURLOPT_TIMEOUT_MS, $timeout);
        curl_setopt($ch, CURLOPT_NOBODY, $body);
        $result = curl_exec($ch);

        $http_code = curl_getinfo($ch, CURLINFO_HTTP_CODE);

        if($http_code != 200){
            return false;
        }
        list($header, $content) = explode("\r\n\r\n", $result, 2);

        $header = explode("\n", $header);

        foreach($header as $key => $item){
            $ex = explode(':', $item, 2);

            if(isset($ex[1]) && $ex[1]){
                $header[trim($ex[0])] = trim($ex[1]);
                unset($header[$key]);
            }
        }

        return ['header' => $header, 'content' => $content];
    }

    /**
     * 初始化CURL选项列表
     * @author tanyanping
     * @var array
     */
    private static $initOptionList = [
        //发起连接最长等待时间(s)
        CURLOPT_CONNECTTIMEOUT => 5,
        //最长请求时间(s)
        CURLOPT_TIMEOUT => 10,
        //将curl_exec()获取的信息以文件流的形式返回
        CURLOPT_RETURNTRANSFER => 1,
        //每次将强制请求一个新连接代替缓存中的连接
        CURLOPT_FRESH_CONNECT => true
    ];

    /**
     * 用户自定义CURL选项列表
     * @author tanyanping
     * @var array
     */
    private static $optionList = [];

    /**
     * CURL结果
     * @author tanyanping
     * @var array
     */
    private static $curlResult;

    /**
     * 设置http请求方式
     * @author tanyanping
     */
    private static function httpMethod($method)
    {
        self::setOption('CUSTOMREQUEST', $method);
    }

    /**
     * 发送CURL请求
     * @author tanyanping
     * @param sting $url 请求地址
     * @return boolean|mixed 请求成功返回结果否则返回false
     */
    private static function request()
    {
        $ch = curl_init();
        curl_setopt_array($ch, self::$initOptionList);
        curl_setopt_array($ch, self::$optionList);
        $result = curl_exec($ch);
        $curlResult = [
            'httpCode' => curl_getinfo($ch, CURLINFO_HTTP_CODE),
            'fileTime' => curl_getinfo($ch, CURLINFO_FILETIME),
            'totalTime' => curl_getinfo($ch, CURLINFO_TOTAL_TIME),
            'nameLookupTime' => curl_getinfo($ch, CURLINFO_NAMELOOKUP_TIME),
            'connectTime ' => curl_getinfo($ch, CURLINFO_CONNECT_TIME),
            'perTransferTime' => curl_getinfo($ch, CURLINFO_PRETRANSFER_TIME),
            'startTransferTime' => curl_getinfo($ch, CURLINFO_STARTTRANSFER_TIME),
            'redirectTime' => curl_getinfo($ch, CURLINFO_REDIRECT_TIME)
        ];
        if(!$result){
            $curlResult['errNo'] = curl_errno($ch);
            $curlResult['errMsg'] = curl_error($ch);
        }
        curl_close($ch);
        self::$curlResult = $curlResult;
        //每次请求后清空配置信息
        self::$optionList = [];
        return $result;
    }

    /**
     * 设置一个CURL选项
     * @author tanyanping
     * @param sting $name 设置CURL选项常量名后缀
     * @param sting $value 设置句柄选项值
     */
    public static function setOption($name, $value)
    {
        self::$optionList[constant('CURLOPT_'.strtoupper($name))] = $value;
    }

    /**
     * 设置多个CURL选项
     * @author tanyanping
     * @param  array $setting
     */
    public static function setOptionArray($setting = [])
    {
        foreach($setting as $name => $value){
            self::setOption($name, $value);
        }
    }

    /**
     * 设置默认值
     * @author tanyanping
     */
    public static function setDetaults()
    {
        self::$optionList = [];
    }

    /**
     * 发送CURL GET请求
     * @author tanyanping
     * @param string $url 请求地址
     * @param array $data 请求数据
     * @return boolean|Ambigous <boolean, mixed>  返回请求的数据
     */
    public static function get($url, $data = [])
    {
        if(!empty($data)){
            $url .= (strpos($url, '?') === false) ? '?' : '&';
            $url .= http_build_query($data);
        }
        self::httpMethod('GET');
        self::setOption('URL', $url);
        self::setOption('HTTPGET', true);
        return self::request();
    }

    /**
     * curl下载文件
     * @author wenyanlei@360.net
     * @param $file_url
     * @return bool|mixed
     */
    public static function getFile($file_url)
    {
        self::httpMethod('GET');
        self::setOption('URL', $file_url);
        self::setOption('ENCODING', '');
        self::setOption('TIMEOUT', 0);
        self::setOption('FOLLOWLOCATION', 1);
        return self::request();
    }

    /**
     * 发送CURL POST请求
     * @author tanyanping
     * @param string $url 请求地址
     * @param array $data 请求数据
     */
    public static function post($url, $data = [])
    {
        self::httpMethod('POST');
        self::setOption('URL', $url);
        self::setOption('POST', true);
        self::setOption('POSTFIELDS', http_build_query($data));
        return self::request();
    }

    /**
     * 发送CURL PUT请求
     * @author tanyanping
     * @param string $url 请求地址
     * @param array $file 发送的文件地址
     */
    public static function put($url, $file)
    {
        self::httpMethod('PUT');
        self::setOption('URL', $url);
        self::setOption('PUT', true);
        //TODO put 请求
        //self::setOption('INFILE', $file);
        //self::setOption('INFILESIZE', $file);
        return self::request();
    }

    /**
     * 发送CURL DELETE请求
     * @author tanyanping
     * @param string $url 请求地址
     */
    public static function delete($url)
    {
        self::httpMethod('DELETE');
        self::setOption('URL', $url);
        self::setOption('CUSTOMREQUEST', 'DELETE');
        return self::request();
    }

    /**
     * 获取CURL请求结果
     * 不传参数key则返回所有信息，参数key区分大小写
     * 参数key的可选值：
     * httpCode                HTTP状态码
     * fileTime                远程获取文档的时间，如果无法获取，则返回值为“-1”
     * totalTime            最后一次传输所消耗的时间
     * nameLookupTime        名称解析所消耗的时间
     * connectTime            建立连接所消耗的时间
     * perTransferTime        从建立连接到准备传输所使用的时间
     * startTransferTime    从建立连接到传输开始所使用的时间
     * redirectTime            在事务传输开始前重定向所使用的时间
     * errNo                错误号
     * errMsg                错误信息
     * @author tanyanping
     * @return mixed
     */
    public static function getResult($key = '')
    {
        if(empty($key)){
            return self::$curlResult;
        }
        if(isset(self::$curlResult[$key])){
            return self::$curlResult[$key];
        }else{
            return false;
        }
    }

    /**
     * 获取HTTP状态码
     * @author tanyanping
     * @return string
     */
    public static function getHttpCode()
    {
        return self::getResult('httpCode');
    }

    /**
     * 获取CURL错误代码
     * @author tanyanping
     * @return string
     */
    public static function getErrNo()
    {
        return self::getResult('errNo');
    }

    /**
     * 获取CURL错误信息
     * @author tanyanping
     * @return string
     */
    public static function getError()
    {
        return self::getResult('errMsg');
    }

    /**
     * [curlPost 外部请求]
     * @param  [type] $url  [description]
     * @param  [type] $data [description]
     * @return [type]       [description]
     */
    public static function curlPostResult($url, $data = '', $flag = 1)
    {

        try{

            if(!empty($data) && !empty($flag))

                $data = http_build_query($data);

            $ch = curl_init();
            curl_setopt($ch, CURLOPT_URL, $url);
            curl_setopt($ch, CURLOPT_POST, 1);
            curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 9);
            curl_setopt($ch, CURLOPT_HEADER, 0);
            curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
            curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
            curl_setopt($ch, CURLOPT_USERAGENT, "Btime Open CMS");
            $result = curl_exec($ch);

            if($result === false) $result = HttpHelper::echoJson(0, 'Curl error: '.curl_error($ch));

            curl_close($ch);
        }catch(Exception $e){

            $result = HttpHelper::echoJson(0, $e->getMessage());
        }

        return $result;
    }

    public static function curlGetResult($url, $data = '', $flag = 1)
    {
        try{
            if(!empty($data) && !empty($flag)) {
                $data = http_build_query($data);
            }
            $ch = curl_init();
            curl_setopt($ch, CURLOPT_URL, $url.'?'.$data);
            curl_setopt($ch, CURLOPT_HEADER, 0);
            curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
            curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'GET');
            $result = curl_exec($ch);
            if($result === false){
                $result = HttpHelper::echoJson(0, 'Curl error: '.curl_error($ch));
            }
            curl_close($ch);
        }catch(Exception $e){

            $result = HttpHelper::echoJson(0, $e->getMessage());
        }

        return $result;
    }

    public static function echoJson($error, $msg)
    {

        $arr = [

            'errorno' => $error,
            'msg' => $msg
        ];

        return json_encode($arr);
    }

    public static function echoJsonResult($error, $msg, $data = '')
    {

        $arr = [

            'errorno' => $error,
            'msg' => $msg,
            'data' => $data
        ];

        return json_encode($arr);
    }

    public static function echoJsonApi($error, $msg)
    {

        $arr = [

            'code' => $error,
            'message' => $msg
        ];

        return json_encode($arr);
    }

    public static function echoJsonResultApi($error, $msg, $data = '')
    {

        $arr = [

            'code' => $error,
            'message' => $msg,
            'data' => $data
        ];

        return json_encode($arr);
    }
}
